#include "reassembler.hh"
#include <algorithm>

using namespace std;

void Reassembler::insert( uint64_t first_index, string data, bool is_last_substring )
{
  // Your code here.
  // 流关闭,容量为零,超出first_unexpected_index的不接受
  if(const uint64_t first_unexpected_index=expected_index_+output_.writer().available_capacity();
  output_.writer().is_closed()||output_.writer().available_capacity()== 0||first_index>=first_unexpected_index)
    return;
  //超出范围的数据被截断,且着子串不做最后一个组
  else if(first_index+data.size()>=first_unexpected_index){
    is_last_substring=false;
    data.resize(first_unexpected_index-first_index);
  }
  //Reassembler了解到适合流可用容量但较早的字节仍然未知），在内部存储它们，直到填补空白，并排序找到index
  if (first_index>expected_index_)
    cache_bytes(first_index,move(data),is_last_substring);
  else//等于的情况
    push_bytes(first_index,move(data),is_last_substring);

  flush_buffer();
}

uint64_t Reassembler::bytes_pending() const
{
  // Your code here.
  return num_pending_;
}

//写入output_
void Reassembler::push_bytes( uint64_t first_index, string data, bool is_last_substring )
{
  if(first_index<expected_index_) //有重复的分组，删除重复部分再push到output
    data.erase(0,expected_index_-first_index);
  expected_index_+=data.size();
  output_.writer().push(move(data));

  if (is_last_substring) {
    output_.writer().close(); // 关闭写端
    unorder_byte_.clear(); // 清空缓冲区
    num_pending_=0;
  }
}

void Reassembler::cache_bytes( uint64_t first_index, string data, bool is_last_substring )
{
  auto end=unorder_byte_.end();
  //找到在unorder_byte_区间大于等于first_index的第一个元素
  auto left=lower_bound(unorder_byte_.begin(),end,first_index,[](auto&& e,uint64_t idx)->bool{
    return idx>(get<0>(e)+get<1>(e).size());
  });
  //找到大于等于first_index+ data.size()的第一个元素即待合并区间右端点的下一个元素
  auto right=upper_bound(left,end,first_index+data.size(),[](uint64_t nxt_idx,auto&&e)->bool{
    return nxt_idx<get<0>(e);
  });

  if(const uint64_t nxt_idx=first_index+data.size();left!=end){
    //取出left的元素
    auto& [l_point,dat,_]=*left;
    // data已存在
    if(const uint64_t r_point=l_point+dat.size();first_index>=l_point&&nxt_idx<=r_point)
      return;
    else if(nxt_idx<l_point){ // data和dat无重叠
      right=left;
    }else if(!(first_index<=l_point&&r_point<=nxt_idx)){ //重叠
      if(first_index>=l_point){ //但dat没被完全覆盖
        data.insert(0,string_view(dat.c_str(),dat.size()-(r_point-first_index)));
      }else{
        data.resize(data.size()-(nxt_idx-l_point));
        data.append(dat); //data在前
      }
      first_index=min(first_index,l_point);
    }
  }

  if(const uint64_t nxt_idx=first_index+data.size();right!=left&&!unorder_byte_.empty()){
    // 如果 right 指向 left，表示两种可能：没有重叠区间、或者只需要合并 left 这个元素
    auto& [l_point,dat,_]=*prev(right);
    if(const uint64_t r_point=l_point+dat.size();r_point>nxt_idx){
      data.resize(data.size()-(nxt_idx-l_point));
      data.append(dat);
    }
  }

  for(;left!=right;left=unorder_byte_.erase(left)){
    num_pending_-=get<1>(*left ).size();
    is_last_substring|=get<2>(*left);
  }
  num_pending_+=data.size();
  unorder_byte_.insert(left,{first_index,move(data),is_last_substring});
}

void Reassembler::flush_buffer()
{
  while(!unorder_byte_.empty()){
    auto&[idx,dat,last]=unorder_byte_.front();
    //乱序,不做任何动作
    if(idx>expected_index_)
      break;
    num_pending_-=dat.size(); // 数据已经被填补上了，立即推入写端
    push_bytes(idx,move(dat),last);
    //最后弹出已写入ByteStream的子串
    if(!unorder_byte_.empty())
      unorder_byte_.pop_front();
  }
}
